package uci

import (
	"code.google.com/p/gochess/notation/cn"
	"code.google.com/p/gochess/notation/fen"
	pos "code.google.com/p/gochess/position"
	"errors"
	"strconv"
	"strings"
)

func parseCommandline(cmdLine string) (cmd, params string, err error) {

	cmd = strings.TrimSpace(cmdLine)
	if len(cmd) == 0 {
		return "", "", errors.New("command line empty")
	}
	idx := strings.Index(cmd, " ")
	if idx == -1 {
		// command only, no parameters
		return
	}
	return cmd[:idx], cmd[idx+1:], nil

}

func parseSetoption(s string) (name, value string, err error) {

	const nameToken = "name"
	const valueToken = "value"
	s = strings.TrimSpace(s)
	if !strings.HasPrefix(s, nameToken) {
		return "", "", errors.New("need 'name' as first token")
	}
	tIdx := strings.Index(s, valueToken)
	if tIdx == -1 {
		//  button type
		return strings.TrimSpace(s[len(nameToken):]), "", nil
	}
	value = strings.TrimSpace(s[tIdx+len(valueToken):])

	if len(value) == 0 {
		return "", "", errors.New("missing parameter for 'value' token")
	}
	name = strings.TrimSpace(s[len(nameToken):tIdx])
	return
}

func parsePosition(s string) (p *pos.Position, err error) {

	s = strings.TrimSpace(s)
	// get index where moves start
	mIdx := strings.Index(s, "moves")
	if mIdx == -1 {
		mIdx = len(s)
	}
	// parse position
	switch {
	case strings.HasPrefix(s, `fen `):
		p, err = fen.Parse(s[len(`fen `):mIdx])
		if err != nil {
			return nil, err
		}
	case strings.HasPrefix(s, "startpos"):
		p = fen.MustParse(fen.InitialPosition)
	default:
		return nil, errors.New("invalid position token")
	}
	if mIdx == len(s) {
		return
	}
	s = strings.TrimSpace(s[mIdx+len("moves"):])
	// parse moves
	if len(s) == 0 {
		return nil, errors.New(`missing move(s) after "moves" token`)
	}
	for len(s) != 0 {
		idx := strings.Index(s, " ")
		if idx == -1 {
			idx = len(s)
		}
		move, err := cn.Parse(p, s[:idx])
		if err != nil {
			return nil, err
		}
		pos.MakeMove(p, move)
		s = strings.TrimSpace(s[idx:])
	}
	return
}

type digitParam struct {
	key   string
	value int32
}

func parseDigitParams(paramLine string) (params []digitParam, err error) {
	a := strings.Fields(paramLine)

	if len(a)/2*2 != len(a) {
		return params, errors.New("need even number of items in parameter list")
	}
	for i := 0; i < len(a); i += 2 {
		value, err := strconv.Atoi(a[i+1])
		if err != nil {
			return []digitParam{}, errors.New("value is not a number")
		}
		params = append(params, digitParam{a[i], int32(value)})
	}
	return
}
